#include "reactor/buffer.hpp"
#include <sys/uio.h>
#include <cerrno>

namespace reactor {

void Buffer::ensureWritableBytes(size_t len) {
    if (writableBytes() < len) {
        makeSpace(len);
    }
}

void Buffer::makeSpace(size_t len) {
    if (writableBytes() + prependableBytes() < len + kCheapPrepend) {
        // 空间不足，需要扩容
        _buffer.resize(_writerIndex + len);
    } else {
        // 空间足够，进行内部整理，将数据前移
        size_t readable = readableBytes();
        std::copy(begin() + _readerIndex, begin() + _writerIndex, begin() + kCheapPrepend);
        _readerIndex = kCheapPrepend;
        _writerIndex = _readerIndex + readable;
    }
}

ssize_t Buffer::readFd(int fd, int* savedErrno) {
    // 使用栈上空间作为临时缓冲区，避免频繁堆分配
    char extrabuf[65536];
    struct iovec vec[2];
    const size_t writable = writableBytes();
    
    vec[0].iov_base = beginWrite();
    vec[0].iov_len = writable;
    vec[1].iov_base = extrabuf;
    vec[1].iov_len = sizeof(extrabuf);
    
    // 当缓冲区空间足够时，只用一个 iovec，否则用两个
    const int iovcnt = (writable < sizeof(extrabuf)) ? 2 : 1;
    const ssize_t n = ::readv(fd, vec, iovcnt);

    if (n < 0) {
        *savedErrno = errno;
    } else if (static_cast<size_t>(n) <= writable) {
        // 读取的数据全在 buffer 内
        _writerIndex += n;
    } else {
        // 读取的数据一部分在 buffer，一部分在 extrabuf
        _writerIndex = _buffer.size();
        append(extrabuf, n - writable);
    }
    return n;
}

} // namespace reactor
